package top.chmin.project.cloud.builder;

import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import top.chmin.project.cloud.common.entity.auto.Entity;
import top.chmin.project.cloud.common.entity.auto.EntityDao;
import top.chmin.project.cloud.common.entity.column.auto.EntityColumn;
import top.chmin.project.cloud.common.entity.column.auto.EntityColumnDao;
import top.chmin.project.cloud.common.entity.column.relation.auto.EntityColumnRelation;
import top.chmin.project.cloud.common.entity.label.value.auto.EntityLabelValueDao;

import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * chmin
 * 2023/12/15 15:21
 * cloud-builder
 */
@Component
public class PageSaveInitBuilder implements Builder {

    @Resource
    EntityDao entityDao;
    @Resource
    EntityColumnDao entityColumnDao;
    @Resource
    EntityLabelValueDao entityLabelValueDao;

    @Override
    public void build(BuilderConfig config) {
        String content = """
                import {BasePage, BaseInput, BaseRule} from "../../%sts/type";
                import {replace} from "../../%sts/util";
                                
                export let #e.fieldName#SaveInit = (page: BasePage) => {
                    let saveModel = page.models.filter(m => 'save' == m.formKey)[0]
                    
                // field input auto
                    
                // field rule auto
                                
                }""".formatted(
                Stream.of(StrUtil.toUnderlineCase(config.getEntity().getClassName()).split("_"))
                        .map(s -> "../")
                        .collect(Collectors.joining()),
                Stream.of(StrUtil.toUnderlineCase(config.getEntity().getClassName()).split("_"))
                        .map(s -> "../")
                        .collect(Collectors.joining())
        );

        String fileName = "\\view\\%sauto\\%sSaveInit.ts".formatted(
                Stream.of(StrUtil.toUnderlineCase(config.getEntity().getClassName()).split("_"))
                        .map(s -> s + "\\")
                        .collect(Collectors.joining()),
                StringUtils.uncapitalize(config.getEntity().getClassName())
        );

        saveUi(config,
                fileName,
                content,
                true
        );

        config.getEntityColumnList().stream()
                .filter(f -> !"id".equals(f.getFieldName()))
                .filter(f -> !"createBy".equals(f.getFieldName()))
                .filter(f -> !"createTime".equals(f.getFieldName()))
                .filter(f -> !"updateBy".equals(f.getFieldName()))
                .filter(f -> !"updateTime".equals(f.getFieldName()))
                .forEach(f -> {
                    Optional<EntityColumnRelation> relation = config.getEntityColumnRelationList()
                            .stream().filter(r -> r.getSourceFieldCode().equals(f.getFieldCode()))
                            .findFirst();
                    if (relation.isPresent()) {
                        EntityColumnRelation r = relation.get();

                        EntityColumn targetValue = getEntityColumn(entityColumnDao, r.getTargetFieldCode());
                        Entity targetEntity = getEntity(entityDao, r.getTargetTableCode());

                        appendUi(config, f,
                                "// field input auto",
                                "new BaseInput('#f.remark#', '#f.fieldName#')",
                                """
                                        saveModel.formInputs.push(replace(new BaseInput('#f.remark#', '#f.fieldName#'), {
                                          inputType: 'select',
                                          options: [],
                                          optionsUrl: '/au/%s/%s/select'
                                        }))""".formatted(
                                        StringUtils.uncapitalize(targetEntity.getClassName()),
                                        targetValue.getFieldName()
                                ),
                                fileName);

                    } else {
                        switch (f.getSimpleType()) {
                            case "String" -> appendUi(config, f,
                                    "// field input auto",
                                    "new BaseInput('#f.remark#', '#f.fieldName#')",
                                    """
                                            saveModel.formInputs.push(replace(new BaseInput('#f.remark#', '#f.fieldName#'), {
                                              span:12
                                            }))""",
                                    fileName);
                            case "LocalDateTime" -> appendUi(config, f,
                                    "// field input auto",
                                    "new BaseInput('#f.remark#', '#f.fieldName#')",
                                    """
                                            saveModel.formInputs.push(replace(new BaseInput('#f.remark#', '#f.fieldName#'), {
                                              inputType: 'datetime',
                                              span:12
                                            }))""",
                                    fileName);
                            case "BigDecimal" -> appendUi(config, f,
                                    "// field input auto",
                                    "new BaseInput('#f.remark#', '#f.fieldName#')",
                                    """
                                            saveModel.formInputs.push(replace(new BaseInput('#f.remark#', '#f.fieldName#'), {
                                              inputType: 'number',
                                              precision: 2,
                                            }))""",
                                    fileName);
                            case null, default -> appendUi(config, f,
                                    "// field input auto",
                                    "new BaseInput('#f.remark#', '#f.fieldName#')",
                                    """
                                            saveModel.formInputs.push(replace(new BaseInput('#f.remark#', '#f.fieldName#'), {
                                              inputType: 'number',
                                              span:12
                                            }))""",
                                    fileName);
                        }
                    }
                });
        config.getEntityColumnList().stream()
                .filter(f -> !"id".equals(f.getFieldName()))
                .filter(f -> !"createBy".equals(f.getFieldName()))
                .filter(f -> !"createTime".equals(f.getFieldName()))
                .filter(f -> !"updateBy".equals(f.getFieldName()))
                .filter(f -> !"updateTime".equals(f.getFieldName()))
                .filter(f -> "NOT NULL".equals(f.getColumnNullable()))
                .forEach(f -> {
                    if ("String".equals(f.getSimpleType())) {
                        appendUi(config, f,
                                "// field rule auto",
                                "saveModel.rules.#f.fieldName#= new BaseRule()",
                                "saveModel.rules.#f.fieldName#= new BaseRule()",
                                fileName);

                    } else {
                        appendUi(config, f,
                                "// field rule auto",
                                "saveModel.rules.#f.fieldName#= new BaseRule()",
                                """
                                        saveModel.rules.#f.fieldName#= replace(new BaseRule(), {
                                            type: 'number'
                                        })
                                        """,
                                fileName);
                    }
                });
    }
}
